|
1
|
|
|
(function () { |
|
2
|
|
|
"use strict"; |
|
3
|
|
|
|
|
4
|
|
|
var BODYTYPES = ["DAYS", "MONTHS", "YEARS"]; |
|
5
|
|
|
|
|
6
|
|
|
/** @typedef {Object.<string, Function[]>} Handlers */ |
|
7
|
|
|
/** @typedef {function(String, Function): null} AddHandler */ |
|
8
|
|
|
/** @typedef {("DAYS"|"MONTHS"|"YEARS")} BodyType */ |
|
9
|
|
|
/** @typedef {string|number} StringNum */ |
|
10
|
|
|
/** @typedef {Object.<string, StringNum>} StringNumObj */ |
|
11
|
|
|
|
|
12
|
|
|
/** |
|
13
|
|
|
* The local state |
|
14
|
|
|
* @typedef {Object} InstanceState |
|
15
|
|
|
* @property {Date} value |
|
16
|
|
|
* @property {Number} year |
|
17
|
|
|
* @property {Number} month |
|
18
|
|
|
* @property {Number} day |
|
19
|
|
|
* @property {Number} time |
|
20
|
|
|
* @property {Number} hours |
|
21
|
|
|
* @property {Number} minutes |
|
22
|
|
|
* @property {Number} seconds |
|
23
|
|
|
* @property {BodyType} bodyType |
|
24
|
|
|
* @property {Boolean} visible |
|
25
|
|
|
* @property {Number} cancelBlur |
|
26
|
|
|
*/ |
|
27
|
|
|
|
|
28
|
|
|
/** |
|
29
|
|
|
* @typedef {Object} Config |
|
30
|
|
|
* @property {String} dateFormat |
|
31
|
|
|
* @property {String} timeFormat |
|
32
|
|
|
* @property {Boolean} showDate |
|
33
|
|
|
* @property {Boolean} showTime |
|
34
|
|
|
* @property {Boolean} showSeconds |
|
35
|
|
|
* @property {Number} paddingX |
|
36
|
|
|
* @property {Number} paddingY |
|
37
|
|
|
* @property {BodyType} defaultView |
|
38
|
|
|
* @property {"TOP"|"BOTTOM"} direction |
|
39
|
|
|
* @property {Array} months |
|
40
|
|
|
* @property {Array} monthsShort |
|
41
|
|
|
* @property {Array} weekdaysShort |
|
42
|
|
|
* @property {Array} timeDescr |
|
43
|
|
|
*/ |
|
44
|
|
|
|
|
45
|
|
|
/** |
|
46
|
|
|
* @class |
|
47
|
|
|
* @param {HTMLElement} elem |
|
48
|
|
|
* @param {Config} config |
|
49
|
|
|
*/ |
|
50
|
|
|
function DTS(elem, config) { |
|
51
|
|
|
var config = config || {}; |
|
52
|
|
|
|
|
53
|
|
|
/** @type {Config} */ |
|
54
|
|
|
var defaultConfig = { |
|
55
|
|
|
defaultView: BODYTYPES[0], |
|
56
|
|
|
dateFormat: "yyyy-mm-dd", |
|
57
|
|
|
timeFormat: "HH:MM:SS", |
|
58
|
|
|
showDate: true, |
|
59
|
|
|
showTime: false, |
|
60
|
|
|
showSeconds: true, |
|
61
|
|
|
paddingX: 5, |
|
62
|
|
|
paddingY: 5, |
|
63
|
|
|
direction: 'TOP', |
|
64
|
|
|
months: [ |
|
65
|
|
|
"January", "February", "March", "April", "May", "June", |
|
66
|
|
|
"July", "August", "September", "October", "November", "December" |
|
67
|
|
|
], |
|
68
|
|
|
monthsShort: [ |
|
69
|
|
|
"Jan", "Feb", "Mar", "Apr", "May", "Jun", |
|
70
|
|
|
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" |
|
71
|
|
|
], |
|
72
|
|
|
weekdaysShort: [ |
|
73
|
|
|
"Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" |
|
74
|
|
|
], |
|
75
|
|
|
timeDescr: [ |
|
76
|
|
|
"HH:", "MM:", "SS:" |
|
77
|
|
|
] |
|
78
|
|
|
} |
|
79
|
|
|
|
|
80
|
|
|
if (!elem) { |
|
81
|
|
|
throw TypeError("input element or selector required for contructor"); |
|
82
|
|
|
} |
|
83
|
|
|
if (Object.getPrototypeOf(elem) === String.prototype) { |
|
84
|
|
|
var _elem = document.querySelectorAll(elem); |
|
85
|
|
|
if (!_elem[0]){ |
|
86
|
|
|
throw Error('"' + elem + '" not found.'); |
|
87
|
|
|
} |
|
88
|
|
|
elem = _elem[0]; |
|
89
|
|
|
} |
|
90
|
|
|
this.config = setDefaults(config, defaultConfig); |
|
91
|
|
|
this.dateFormat = this.config.dateFormat; |
|
92
|
|
|
this.timeFormat = this.config.timeFormat; |
|
93
|
|
|
this.dateFormatRegEx = new RegExp("yyyy|yy|mm|dd", "gi"); |
|
94
|
|
|
this.timeFormatRegEx = new RegExp("hh|mm|ss|a", "gi"); |
|
95
|
|
|
this.inputElem = elem; |
|
96
|
|
|
this.dtbox = null; |
|
97
|
|
|
this.setup(); |
|
98
|
|
|
} |
|
99
|
|
|
DTS.prototype.setup = function () { |
|
100
|
|
|
var handler = this.inputElemHandler.bind(this); |
|
101
|
|
|
this.inputElem.addEventListener("focus", handler, false) |
|
102
|
|
|
this.inputElem.addEventListener("blur", handler, false); |
|
103
|
|
|
} |
|
104
|
|
|
DTS.prototype.inputElemHandler = function (e) { |
|
105
|
|
|
if (e.type == "focus") { |
|
106
|
|
|
if (!this.dtbox) { |
|
107
|
|
|
this.dtbox = new DTBox(e.target, this); |
|
108
|
|
|
} |
|
109
|
|
|
this.dtbox.visible = true; |
|
110
|
|
|
} else if (e.type == "blur" && this.dtbox && this.dtbox.visible) { |
|
111
|
|
|
var self = this; |
|
112
|
|
|
setTimeout(function () { |
|
113
|
|
|
if (self.dtbox.cancelBlur > 0) { |
|
114
|
|
|
self.dtbox.cancelBlur -= 1; |
|
115
|
|
|
} else { |
|
116
|
|
|
self.dtbox.visible = false; |
|
117
|
|
|
self.inputElem.blur(); |
|
118
|
|
|
} |
|
119
|
|
|
}, 100); |
|
120
|
|
|
} |
|
121
|
|
|
} |
|
122
|
|
|
/** |
|
123
|
|
|
* @class |
|
124
|
|
|
* @param {HTMLElement} elem |
|
125
|
|
|
* @param {DTS} settings |
|
126
|
|
|
*/ |
|
127
|
|
|
function DTBox(elem, settings) { |
|
128
|
|
|
/** @type {DTBox} */ |
|
129
|
|
|
var self = this; |
|
130
|
|
|
|
|
131
|
|
|
/** @type {Handlers} */ |
|
132
|
|
|
var handlers = {}; |
|
133
|
|
|
|
|
134
|
|
|
/** @type {InstanceState} */ |
|
135
|
|
|
var localState = {}; |
|
136
|
|
|
|
|
137
|
|
|
/** |
|
138
|
|
|
* @param {String} key |
|
139
|
|
|
* @param {*} default_val |
|
140
|
|
|
*/ |
|
141
|
|
|
function getterSetter(key, default_val) { |
|
142
|
|
|
return { |
|
143
|
|
|
get: function () { |
|
144
|
|
|
var val = localState[key]; |
|
145
|
|
|
return val === undefined ? default_val : val; |
|
146
|
|
|
}, |
|
147
|
|
|
set: function (val) { |
|
148
|
|
|
var prevState = self.state; |
|
149
|
|
|
var _handlers = handlers[key] || []; |
|
150
|
|
|
localState[key] = val; |
|
151
|
|
|
for (var i = 0; i < _handlers.length; i++) { |
|
152
|
|
|
_handlers[i].bind(self)(localState, prevState); |
|
153
|
|
|
} |
|
154
|
|
|
}, |
|
155
|
|
|
}; |
|
156
|
|
|
}; |
|
157
|
|
|
|
|
158
|
|
|
/** @type {AddHandler} */ |
|
159
|
|
|
function addHandler(key, handlerFn) { |
|
160
|
|
|
if (!key || !handlerFn) { |
|
161
|
|
|
return false; |
|
162
|
|
|
} |
|
163
|
|
|
if (!handlers[key]) { |
|
164
|
|
|
handlers[key] = []; |
|
165
|
|
|
} |
|
166
|
|
|
handlers[key].push(handlerFn); |
|
|
|
|
|
|
167
|
|
|
} |
|
168
|
|
|
|
|
169
|
|
|
Object.defineProperties(this, { |
|
170
|
|
|
visible: getterSetter("visible", false), |
|
171
|
|
|
bodyType: getterSetter("bodyType", settings.config.defaultView), |
|
172
|
|
|
value: getterSetter("value"), |
|
173
|
|
|
year: getterSetter("year", 0), |
|
174
|
|
|
month: getterSetter("month", 0), |
|
175
|
|
|
day: getterSetter("day", 0), |
|
176
|
|
|
hours: getterSetter("hours", 0), |
|
177
|
|
|
minutes: getterSetter("minutes", 0), |
|
178
|
|
|
seconds: getterSetter("seconds", 0), |
|
179
|
|
|
cancelBlur: getterSetter("cancelBlur", 0), |
|
180
|
|
|
addHandler: {value: addHandler}, |
|
181
|
|
|
month_long: { |
|
182
|
|
|
get: function () { |
|
183
|
|
|
return self.settings.config.months[self.month]; |
|
184
|
|
|
}, |
|
185
|
|
|
}, |
|
186
|
|
|
month_short: { |
|
187
|
|
|
get: function () { |
|
188
|
|
|
return self.settings.config.monthsShort[self.month] |
|
189
|
|
|
}, |
|
190
|
|
|
}, |
|
191
|
|
|
state: { |
|
192
|
|
|
get: function () { |
|
193
|
|
|
return Object.assign({}, localState); |
|
194
|
|
|
}, |
|
195
|
|
|
}, |
|
196
|
|
|
time: { |
|
197
|
|
|
get: function() { |
|
198
|
|
|
var hours = self.hours * 60 * 60 * 1000; |
|
199
|
|
|
var minutes = self.minutes * 60 * 1000; |
|
200
|
|
|
var seconds = self.seconds * 1000; |
|
201
|
|
|
return hours + minutes + seconds; |
|
202
|
|
|
} |
|
203
|
|
|
}, |
|
204
|
|
|
}); |
|
205
|
|
|
this.el = {}; |
|
206
|
|
|
this.settings = settings; |
|
207
|
|
|
this.elem = elem; |
|
208
|
|
|
this.setup(); |
|
209
|
|
|
} |
|
210
|
|
|
DTBox.prototype.setup = function () { |
|
211
|
|
|
Object.defineProperties(this.el, { |
|
212
|
|
|
wrapper: { value: null, configurable: true }, |
|
213
|
|
|
header: { value: null, configurable: true }, |
|
214
|
|
|
body: { value: null, configurable: true }, |
|
215
|
|
|
footer: { value: null, configurable: true } |
|
216
|
|
|
}); |
|
217
|
|
|
this.setupWrapper(); |
|
218
|
|
|
if (this.settings.config.showDate) { |
|
219
|
|
|
this.setupHeader(); |
|
220
|
|
|
this.setupBody(); |
|
221
|
|
|
} |
|
222
|
|
|
if (this.settings.config.showTime) { |
|
223
|
|
|
this.setupFooter(); |
|
224
|
|
|
} |
|
225
|
|
|
|
|
226
|
|
|
var self = this; |
|
227
|
|
|
this.addHandler("visible", function (state, prevState) { |
|
228
|
|
|
if (state.visible && !prevState.visible){ |
|
229
|
|
|
document.body.appendChild(this.el.wrapper); |
|
230
|
|
|
|
|
231
|
|
|
var parts = self.elem.value.split(/\s*,\s*/); |
|
232
|
|
|
var startDate = undefined; |
|
|
|
|
|
|
233
|
|
|
var startTime = 0; |
|
234
|
|
|
if (self.settings.config.showDate) { |
|
235
|
|
|
startDate = parseDate(parts[0], self.settings); |
|
236
|
|
|
} |
|
237
|
|
|
if (self.settings.config.showTime) { |
|
238
|
|
|
startTime = parseTime(parts[parts.length-1], self.settings); |
|
239
|
|
|
startTime = startTime || 0; |
|
240
|
|
|
} |
|
241
|
|
|
if (!(startDate && startDate.getTime())) { |
|
242
|
|
|
startDate = new Date(); |
|
243
|
|
|
startDate = new Date( |
|
244
|
|
|
startDate.getFullYear(), |
|
245
|
|
|
startDate.getMonth(), |
|
246
|
|
|
startDate.getDate() |
|
247
|
|
|
); |
|
248
|
|
|
} |
|
249
|
|
|
var value = new Date(startDate.getTime() + startTime); |
|
250
|
|
|
self.value = value; |
|
251
|
|
|
self.year = value.getFullYear(); |
|
252
|
|
|
self.month = value.getMonth(); |
|
253
|
|
|
self.day = value.getDate(); |
|
254
|
|
|
self.hours = value.getHours(); |
|
255
|
|
|
self.minutes = value.getMinutes(); |
|
256
|
|
|
self.seconds = value.getSeconds(); |
|
257
|
|
|
|
|
258
|
|
|
if (self.settings.config.showDate) { |
|
259
|
|
|
self.setHeaderContent(); |
|
260
|
|
|
self.setBodyContent(); |
|
261
|
|
|
} |
|
262
|
|
|
if (self.settings.config.showTime) { |
|
263
|
|
|
self.setFooterContent(); |
|
264
|
|
|
} |
|
265
|
|
|
} else if (!state.visible && prevState.visible) { |
|
266
|
|
|
document.body.removeChild(this.el.wrapper); |
|
267
|
|
|
} |
|
268
|
|
|
}); |
|
269
|
|
|
} |
|
270
|
|
|
DTBox.prototype.setupWrapper = function () { |
|
271
|
|
|
if (!this.el.wrapper) { |
|
272
|
|
|
var el = document.createElement("div"); |
|
273
|
|
|
el.classList.add("date-selector-wrapper"); |
|
274
|
|
|
Object.defineProperty(this.el, "wrapper", { value: el }); |
|
275
|
|
|
} |
|
276
|
|
|
var self = this; |
|
277
|
|
|
var htmlRoot = document.getElementsByTagName('html')[0]; |
|
278
|
|
|
function setPosition(e){ |
|
|
|
|
|
|
279
|
|
|
var minTopSpace = 300; |
|
280
|
|
|
var box = getOffset(self.elem); |
|
281
|
|
|
var config = self.settings.config; |
|
282
|
|
|
var paddingY = config.paddingY || 5; |
|
283
|
|
|
var paddingX = config.paddingX || 5; |
|
284
|
|
|
var top = box.top + self.elem.offsetHeight + paddingY; |
|
285
|
|
|
var left = box.left + paddingX; |
|
286
|
|
|
var bottom = htmlRoot.clientHeight - box.top + paddingY; |
|
287
|
|
|
|
|
288
|
|
|
self.el.wrapper.style.left = `${left}px`; |
|
289
|
|
|
if (box.top > minTopSpace && config.direction != 'BOTTOM') { |
|
290
|
|
|
self.el.wrapper.style.bottom = `${bottom}px`; |
|
291
|
|
|
self.el.wrapper.style.top = ''; |
|
292
|
|
|
} else { |
|
293
|
|
|
self.el.wrapper.style.top = `${top}px`; |
|
294
|
|
|
self.el.wrapper.style.bottom = ''; |
|
295
|
|
|
} |
|
296
|
|
|
} |
|
297
|
|
|
|
|
298
|
|
|
function handler(e) { |
|
|
|
|
|
|
299
|
|
|
self.cancelBlur += 1; |
|
300
|
|
|
setTimeout(function(){ |
|
301
|
|
|
self.elem.focus(); |
|
302
|
|
|
}, 50); |
|
303
|
|
|
} |
|
304
|
|
|
setPosition(); |
|
305
|
|
|
this.setPosition = setPosition; |
|
306
|
|
|
this.el.wrapper.addEventListener("mousedown", handler, false); |
|
307
|
|
|
this.el.wrapper.addEventListener("touchstart", handler, false); |
|
308
|
|
|
window.addEventListener('resize', this.setPosition); |
|
309
|
|
|
} |
|
310
|
|
|
DTBox.prototype.setupHeader = function () { |
|
311
|
|
|
if (!this.el.header) { |
|
312
|
|
|
var row = document.createElement("div"); |
|
313
|
|
|
var classes = ["cal-nav-prev", "cal-nav-current", "cal-nav-next"]; |
|
314
|
|
|
row.classList.add("cal-header"); |
|
315
|
|
|
for (var i = 0; i < 3; i++) { |
|
316
|
|
|
var cell = document.createElement("div"); |
|
317
|
|
|
cell.classList.add("cal-nav", classes[i]); |
|
318
|
|
|
cell.onclick = this.onHeaderChange.bind(this); |
|
319
|
|
|
row.appendChild(cell); |
|
320
|
|
|
} |
|
321
|
|
|
row.children[0].innerHTML = "◀"; // "<"; |
|
322
|
|
|
row.children[2].innerHTML = "▶"; // ">"; |
|
323
|
|
|
Object.defineProperty(this.el, "header", { value: row }); |
|
324
|
|
|
tryAppendChild(row, this.el.wrapper); |
|
325
|
|
|
} |
|
326
|
|
|
this.setHeaderContent(); |
|
327
|
|
|
} |
|
328
|
|
|
DTBox.prototype.setHeaderContent = function () { |
|
329
|
|
|
var content = this.year; |
|
330
|
|
|
if ("DAYS" == this.bodyType) { |
|
331
|
|
|
content = this.month_long + " " + content; |
|
332
|
|
|
} else if ("YEARS" == this.bodyType) { |
|
333
|
|
|
var start = this.year + 10 - (this.year % 10); |
|
334
|
|
|
content = start - 10 + "-" + (start - 1); |
|
335
|
|
|
} |
|
336
|
|
|
this.el.header.children[1].innerText = content; |
|
337
|
|
|
} |
|
338
|
|
|
DTBox.prototype.setupBody = function () { |
|
339
|
|
|
if (!this.el.body) { |
|
340
|
|
|
var el = document.createElement("div"); |
|
341
|
|
|
el.classList.add("cal-body"); |
|
342
|
|
|
Object.defineProperty(this.el, "body", { value: el }); |
|
343
|
|
|
tryAppendChild(el, this.el.wrapper); |
|
344
|
|
|
} |
|
345
|
|
|
var toAppend = null; |
|
346
|
|
|
function makeGrid(rows, cols, className, firstRowClass, clickHandler) { |
|
347
|
|
|
var grid = document.createElement("div"); |
|
348
|
|
|
grid.classList.add(className); |
|
349
|
|
|
for (var i = 1; i < rows + 1; i++) { |
|
350
|
|
|
var row = document.createElement("div"); |
|
351
|
|
|
row.classList.add("cal-row", "cal-row-" + i); |
|
352
|
|
|
if (i == 1 && firstRowClass) { |
|
|
|
|
|
|
353
|
|
|
row.classList.add(firstRowClass); |
|
354
|
|
|
} |
|
355
|
|
|
for (var j = 1; j < cols + 1; j++) { |
|
356
|
|
|
var col = document.createElement("div"); |
|
357
|
|
|
col.classList.add("cal-cell", "cal-col-" + j); |
|
358
|
|
|
col.onclick = clickHandler; |
|
359
|
|
|
row.appendChild(col); |
|
360
|
|
|
} |
|
361
|
|
|
grid.appendChild(row); |
|
362
|
|
|
} |
|
363
|
|
|
return grid; |
|
364
|
|
|
} |
|
365
|
|
|
if ("DAYS" == this.bodyType) { |
|
366
|
|
|
toAppend = this.el.body.calDays; |
|
367
|
|
|
if (!toAppend) { |
|
368
|
|
|
toAppend = makeGrid(7, 7, "cal-days", "cal-day-names", this.onDateSelected.bind(this)); |
|
369
|
|
|
for (var i = 0; i < 7; i++) { |
|
370
|
|
|
var cell = toAppend.children[0].children[i]; |
|
371
|
|
|
cell.innerText = this.settings.config.weekdaysShort[i]; |
|
372
|
|
|
cell.onclick = null; |
|
373
|
|
|
} |
|
374
|
|
|
this.el.body.calDays = toAppend; |
|
375
|
|
|
} |
|
376
|
|
|
} else if ("MONTHS" == this.bodyType) { |
|
377
|
|
|
toAppend = this.el.body.calMonths; |
|
378
|
|
|
if (!toAppend) { |
|
379
|
|
|
toAppend = makeGrid(3, 4, "cal-months", null, this.onMonthSelected.bind(this)); |
|
380
|
|
|
for (var i = 0; i < 3; i++) { |
|
|
|
|
|
|
381
|
|
|
for (var j = 0; j < 4; j++) { |
|
382
|
|
|
var monthShort = this.settings.config.monthsShort[4 * i + j]; |
|
383
|
|
|
toAppend.children[i].children[j].innerText = monthShort; |
|
384
|
|
|
} |
|
385
|
|
|
} |
|
386
|
|
|
this.el.body.calMonths = toAppend; |
|
387
|
|
|
} |
|
388
|
|
|
} else if ("YEARS" == this.bodyType) { |
|
389
|
|
|
toAppend = this.el.body.calYears; |
|
390
|
|
|
if (!toAppend) { |
|
391
|
|
|
toAppend = makeGrid(3, 4, "cal-years", null, this.onYearSelected.bind(this)); |
|
392
|
|
|
this.el.body.calYears = toAppend; |
|
393
|
|
|
} |
|
394
|
|
|
} |
|
395
|
|
|
empty(this.el.body); |
|
396
|
|
|
tryAppendChild(toAppend, this.el.body); |
|
397
|
|
|
this.setBodyContent(); |
|
398
|
|
|
} |
|
399
|
|
|
DTBox.prototype.setBodyContent = function () { |
|
400
|
|
|
var grid = this.el.body.children[0]; |
|
401
|
|
|
var classes = ["cal-cell-prev", "cal-cell-next", "cal-value"]; |
|
402
|
|
|
if ("DAYS" == this.bodyType) { |
|
403
|
|
|
var oneDayMilliSecs = 24 * 60 * 60 * 1000; |
|
404
|
|
|
var start = new Date(this.year, this.month, 1); |
|
405
|
|
|
var adjusted = new Date(start.getTime() - oneDayMilliSecs * start.getDay()); |
|
406
|
|
|
|
|
407
|
|
|
grid.children[6].style.display = ""; |
|
408
|
|
|
for (var i = 1; i < 7; i++) { |
|
409
|
|
|
for (var j = 0; j < 7; j++) { |
|
410
|
|
|
var cell = grid.children[i].children[j]; |
|
411
|
|
|
var month = adjusted.getMonth(); |
|
412
|
|
|
var date = adjusted.getDate(); |
|
413
|
|
|
|
|
414
|
|
|
cell.innerText = date; |
|
415
|
|
|
cell.classList.remove(classes[0], classes[1], classes[2]); |
|
416
|
|
|
if (month != this.month) { |
|
417
|
|
|
if (i == 6 && j == 0) { |
|
|
|
|
|
|
418
|
|
|
grid.children[6].style.display = "none"; |
|
419
|
|
|
break; |
|
420
|
|
|
} |
|
421
|
|
|
cell.classList.add(month < this.month ? classes[0] : classes[1]); |
|
422
|
|
|
} else if (isEqualDate(adjusted, this.value)){ |
|
423
|
|
|
cell.classList.add(classes[2]); |
|
424
|
|
|
} |
|
425
|
|
|
adjusted = new Date(adjusted.getTime() + oneDayMilliSecs); |
|
426
|
|
|
} |
|
427
|
|
|
} |
|
428
|
|
|
} else if ("YEARS" == this.bodyType) { |
|
429
|
|
|
var year = this.year - (this.year % 10) - 1; |
|
430
|
|
|
for (i = 0; i < 3; i++) { |
|
431
|
|
|
for (j = 0; j < 4; j++) { |
|
432
|
|
|
grid.children[i].children[j].innerText = year; |
|
433
|
|
|
year += 1; |
|
434
|
|
|
} |
|
435
|
|
|
} |
|
436
|
|
|
grid.children[0].children[0].classList.add(classes[0]); |
|
437
|
|
|
grid.children[2].children[3].classList.add(classes[1]); |
|
438
|
|
|
} |
|
439
|
|
|
} |
|
440
|
|
|
|
|
441
|
|
|
/** @param {Event} e */ |
|
442
|
|
|
DTBox.prototype.onTimeChange = function(e) { |
|
443
|
|
|
e.stopPropagation(); |
|
444
|
|
|
if (e.type == 'mousedown') { |
|
445
|
|
|
this.cancelBlur += 1; |
|
446
|
|
|
return; |
|
447
|
|
|
} |
|
448
|
|
|
if (e.type == 'mouseup') { |
|
449
|
|
|
var self = this; |
|
450
|
|
|
setTimeout(function(){ |
|
451
|
|
|
self.elem.focus(); |
|
452
|
|
|
}, 50); |
|
453
|
|
|
return; |
|
454
|
|
|
} |
|
455
|
|
|
|
|
456
|
|
|
var el = e.target; |
|
457
|
|
|
this[el.name] = parseInt(el.value) || 0; |
|
458
|
|
|
this.setupFooter(); |
|
459
|
|
|
this.setInputValue(); |
|
460
|
|
|
} |
|
461
|
|
|
|
|
462
|
|
|
DTBox.prototype.setupFooter = function() { |
|
463
|
|
|
if (!this.el.footer) { |
|
464
|
|
|
var footer = document.createElement("div"); |
|
465
|
|
|
var handler = this.onTimeChange.bind(this); |
|
466
|
|
|
var self = this; |
|
467
|
|
|
|
|
468
|
|
|
function makeRow(label, name, range, changeHandler) { |
|
|
|
|
|
|
469
|
|
|
var row = document.createElement("div"); |
|
470
|
|
|
row.classList.add('cal-time'); |
|
471
|
|
|
|
|
472
|
|
|
var labelCol = row.appendChild(document.createElement("div")); |
|
473
|
|
|
labelCol.classList.add('cal-time-label'); |
|
474
|
|
|
labelCol.innerText = label; |
|
475
|
|
|
|
|
476
|
|
|
var valueCol = row.appendChild(document.createElement("div")); |
|
477
|
|
|
valueCol.classList.add('cal-time-value'); |
|
478
|
|
|
valueCol.innerText = '00'; |
|
479
|
|
|
|
|
480
|
|
|
var inputCol = row.appendChild(document.createElement("div")); |
|
481
|
|
|
var slider = inputCol.appendChild(document.createElement("input")); |
|
482
|
|
|
Object.assign(slider, {step:1, min:0, max:range, name:name, type:'range'}); |
|
483
|
|
|
Object.defineProperty(footer, name, {value: slider}); |
|
484
|
|
|
inputCol.classList.add('cal-time-slider'); |
|
485
|
|
|
slider.onchange = changeHandler; |
|
486
|
|
|
slider.oninput = changeHandler; |
|
487
|
|
|
slider.onmousedown = changeHandler; |
|
488
|
|
|
slider.onmouseup = changeHandler; |
|
489
|
|
|
self[name] = self[name] || parseInt(slider.value) || 0; |
|
490
|
|
|
footer.appendChild(row) |
|
491
|
|
|
} |
|
492
|
|
|
makeRow(this.settings.config.timeDescr[0], 'hours', 23, handler); |
|
493
|
|
|
makeRow(this.settings.config.timeDescr[1], 'minutes', 59, handler); |
|
494
|
|
|
if (this.settings.config.showSeconds) { |
|
495
|
|
|
makeRow(this.settings.config.timeDescr[2], 'seconds', 59, handler); |
|
496
|
|
|
} |
|
497
|
|
|
|
|
498
|
|
|
footer.classList.add("cal-footer"); |
|
499
|
|
|
Object.defineProperty(this.el, "footer", { value: footer }); |
|
500
|
|
|
tryAppendChild(footer, this.el.wrapper); |
|
501
|
|
|
} |
|
502
|
|
|
this.setFooterContent(); |
|
503
|
|
|
} |
|
504
|
|
|
|
|
505
|
|
|
DTBox.prototype.setFooterContent = function() { |
|
506
|
|
|
if (this.el.footer) { |
|
507
|
|
|
var footer = this.el.footer; |
|
508
|
|
|
footer.hours.value = this.hours; |
|
509
|
|
|
footer.children[0].children[1].innerText = padded(this.hours, 2); |
|
510
|
|
|
footer.minutes.value = this.minutes; |
|
511
|
|
|
footer.children[1].children[1].innerText = padded(this.minutes, 2); |
|
512
|
|
|
if (this.settings.config.showSeconds) { |
|
513
|
|
|
footer.seconds.value = this.seconds; |
|
514
|
|
|
footer.children[2].children[1].innerText = padded(this.seconds, 2); |
|
515
|
|
|
} |
|
516
|
|
|
} |
|
517
|
|
|
} |
|
518
|
|
|
|
|
519
|
|
|
DTBox.prototype.setInputValue = function() { |
|
520
|
|
|
var date = new Date(this.year, this.month, this.day); |
|
521
|
|
|
var strings = []; |
|
522
|
|
|
if (this.settings.config.showDate) { |
|
523
|
|
|
strings.push(renderDate(date, this.settings)); |
|
524
|
|
|
} |
|
525
|
|
|
if (this.settings.config.showTime) { |
|
526
|
|
|
var joined = new Date(date.getTime() + this.time); |
|
527
|
|
|
strings.push(renderTime(joined, this.settings)); |
|
528
|
|
|
} |
|
529
|
|
|
this.elem.value = strings.join(', '); |
|
530
|
|
|
} |
|
531
|
|
|
|
|
532
|
|
|
DTBox.prototype.onDateSelected = function (e) { |
|
533
|
|
|
var row = e.target.parentNode; |
|
534
|
|
|
var date = parseInt(e.target.innerText); |
|
535
|
|
|
if (!(row.nextSibling && row.nextSibling.nextSibling) && date < 8) { |
|
536
|
|
|
this.month += 1; |
|
537
|
|
|
} else if (!(row.previousSibling && row.previousSibling.previousSibling) && date > 7) { |
|
538
|
|
|
this.month -= 1; |
|
539
|
|
|
} |
|
540
|
|
|
this.day = parseInt(e.target.innerText); |
|
541
|
|
|
this.value = new Date(this.year, this.month, this.day); |
|
542
|
|
|
this.setInputValue(); |
|
543
|
|
|
this.setHeaderContent(); |
|
544
|
|
|
this.setBodyContent(); |
|
545
|
|
|
} |
|
546
|
|
|
|
|
547
|
|
|
/** @param {Event} e */ |
|
548
|
|
|
DTBox.prototype.onMonthSelected = function (e) { |
|
549
|
|
|
var col = 0; |
|
550
|
|
|
var row = 2; |
|
551
|
|
|
var cell = e.target; |
|
552
|
|
|
if (cell.parentNode.nextSibling){ |
|
553
|
|
|
row = cell.parentNode.previousSibling ? 1: 0; |
|
554
|
|
|
} |
|
555
|
|
|
if (cell.previousSibling) { |
|
556
|
|
|
col = 3; |
|
557
|
|
|
if (cell.nextSibling) { |
|
558
|
|
|
col = cell.previousSibling.previousSibling ? 2 : 1; |
|
559
|
|
|
} |
|
560
|
|
|
} |
|
561
|
|
|
this.month = 4 * row + col; |
|
562
|
|
|
this.bodyType = "DAYS"; |
|
563
|
|
|
this.setHeaderContent(); |
|
564
|
|
|
this.setupBody(); |
|
565
|
|
|
} |
|
566
|
|
|
|
|
567
|
|
|
/** @param {Event} e */ |
|
568
|
|
|
DTBox.prototype.onYearSelected = function (e) { |
|
569
|
|
|
this.year = parseInt(e.target.innerText); |
|
570
|
|
|
this.bodyType = "MONTHS"; |
|
571
|
|
|
this.setHeaderContent(); |
|
572
|
|
|
this.setupBody(); |
|
573
|
|
|
} |
|
574
|
|
|
|
|
575
|
|
|
/** @param {Event} e */ |
|
576
|
|
|
DTBox.prototype.onHeaderChange = function (e) { |
|
577
|
|
|
var cell = e.target; |
|
578
|
|
|
if (cell.previousSibling && cell.nextSibling) { |
|
579
|
|
|
var idx = BODYTYPES.indexOf(this.bodyType); |
|
580
|
|
|
if (idx < 0 || !BODYTYPES[idx + 1]) { |
|
581
|
|
|
return; |
|
582
|
|
|
} |
|
583
|
|
|
this.bodyType = BODYTYPES[idx + 1]; |
|
584
|
|
|
this.setupBody(); |
|
585
|
|
|
} else { |
|
586
|
|
|
var sign = cell.previousSibling ? 1 : -1; |
|
587
|
|
|
switch (this.bodyType) { |
|
588
|
|
|
case "DAYS": |
|
589
|
|
|
this.month += sign * 1; |
|
590
|
|
|
break; |
|
591
|
|
|
case "MONTHS": |
|
592
|
|
|
this.year += sign * 1; |
|
593
|
|
|
break; |
|
594
|
|
|
case "YEARS": |
|
595
|
|
|
this.year += sign * 10; |
|
596
|
|
|
} |
|
597
|
|
|
if (this.month > 11 || this.month < 0) { |
|
598
|
|
|
this.year += Math.floor(this.month / 11); |
|
599
|
|
|
this.month = this.month > 11 ? 0 : 11; |
|
600
|
|
|
} |
|
601
|
|
|
} |
|
602
|
|
|
this.setHeaderContent(); |
|
603
|
|
|
this.setBodyContent(); |
|
604
|
|
|
} |
|
605
|
|
|
|
|
606
|
|
|
|
|
607
|
|
|
/** |
|
608
|
|
|
* @param {HTMLElement} elem |
|
609
|
|
|
* @returns {{left:number, top:number}} |
|
610
|
|
|
*/ |
|
611
|
|
|
function getOffset(elem) { |
|
612
|
|
|
var box = elem.getBoundingClientRect(); |
|
613
|
|
|
var left = window.pageXOffset !== undefined ? window.pageXOffset : |
|
614
|
|
|
(document.documentElement || document.body.parentNode || document.body).scrollLeft; |
|
615
|
|
|
var top = window.pageYOffset !== undefined ? window.pageYOffset : |
|
616
|
|
|
(document.documentElement || document.body.parentNode || document.body).scrollTop; |
|
617
|
|
|
return { left: box.left + left, top: box.top + top }; |
|
618
|
|
|
} |
|
619
|
|
|
function empty(e) { |
|
620
|
|
|
for (; e.children.length; ) e.removeChild(e.children[0]); |
|
|
|
|
|
|
621
|
|
|
} |
|
622
|
|
|
function tryAppendChild(newChild, refNode) { |
|
623
|
|
|
try { |
|
624
|
|
|
refNode.appendChild(newChild); |
|
625
|
|
|
return newChild; |
|
626
|
|
|
} catch (e) { |
|
627
|
|
|
console.trace(e); |
|
|
|
|
|
|
628
|
|
|
} |
|
629
|
|
|
} |
|
630
|
|
|
|
|
631
|
|
|
/** @class */ |
|
632
|
|
|
function hookFuncs() { |
|
633
|
|
|
/** @type {Handlers} */ |
|
634
|
|
|
this._funcs = {}; |
|
635
|
|
|
} |
|
636
|
|
|
/** |
|
637
|
|
|
* @param {string} key |
|
638
|
|
|
* @param {Function} func |
|
639
|
|
|
*/ |
|
640
|
|
|
hookFuncs.prototype.add = function(key, func){ |
|
641
|
|
|
if (!this._funcs[key]){ |
|
642
|
|
|
this._funcs[key] = []; |
|
643
|
|
|
} |
|
644
|
|
|
this._funcs[key].push(func) |
|
645
|
|
|
} |
|
646
|
|
|
/** |
|
647
|
|
|
* @param {String} key |
|
648
|
|
|
* @returns {Function[]} handlers |
|
649
|
|
|
*/ |
|
650
|
|
|
hookFuncs.prototype.get = function(key){ |
|
651
|
|
|
return this._funcs[key] ? this._funcs[key] : []; |
|
652
|
|
|
} |
|
653
|
|
|
|
|
654
|
|
|
/** |
|
655
|
|
|
* @param {Array.<string>} arr |
|
656
|
|
|
* @param {String} string |
|
657
|
|
|
* @returns {Array.<string>} sorted string |
|
658
|
|
|
*/ |
|
659
|
|
|
function sortByStringIndex(arr, string) { |
|
660
|
|
|
return arr.sort(function(a, b){ |
|
661
|
|
|
var h = string.indexOf(a); |
|
662
|
|
|
var l = string.indexOf(b); |
|
663
|
|
|
var rank = 0; |
|
664
|
|
|
if (h < l) { |
|
665
|
|
|
rank = -1; |
|
666
|
|
|
} else if (l < h) { |
|
667
|
|
|
rank = 1; |
|
668
|
|
|
} else if (a.length > b.length) { |
|
669
|
|
|
rank = -1; |
|
670
|
|
|
} else if (b.length > a.length) { |
|
671
|
|
|
rank = 1; |
|
672
|
|
|
} |
|
673
|
|
|
return rank; |
|
674
|
|
|
}); |
|
675
|
|
|
} |
|
676
|
|
|
|
|
677
|
|
|
/** |
|
678
|
|
|
* Remove keys from array that are not in format |
|
679
|
|
|
* @param {string[]} keys |
|
680
|
|
|
* @param {string} format |
|
681
|
|
|
* @returns {string[]} new filtered array |
|
682
|
|
|
*/ |
|
683
|
|
|
function filterFormatKeys(keys, format) { |
|
684
|
|
|
var out = []; |
|
685
|
|
|
var formatIdx = 0; |
|
686
|
|
|
for (var i = 0; i<keys.length; i++) { |
|
687
|
|
|
var key = keys[i]; |
|
688
|
|
|
if (format.slice(formatIdx).indexOf(key) > -1) { |
|
689
|
|
|
formatIdx += key.length; |
|
690
|
|
|
out.push(key); |
|
691
|
|
|
} |
|
692
|
|
|
} |
|
693
|
|
|
return out; |
|
694
|
|
|
} |
|
695
|
|
|
|
|
696
|
|
|
/** |
|
697
|
|
|
* @template {StringNumObj} FormatObj |
|
698
|
|
|
* @param {string} value |
|
699
|
|
|
* @param {string} format |
|
700
|
|
|
* @param {FormatObj} formatObj |
|
701
|
|
|
* @param {function(Object.<string, hookFuncs>): null} setHooks |
|
702
|
|
|
* @returns {FormatObj} formatObj |
|
703
|
|
|
*/ |
|
704
|
|
|
function parseData(value, format, formatObj, setHooks) { |
|
705
|
|
|
var hooks = { |
|
706
|
|
|
canSkip: new hookFuncs(), |
|
|
|
|
|
|
707
|
|
|
updateValue: new hookFuncs(), |
|
|
|
|
|
|
708
|
|
|
} |
|
709
|
|
|
var keys = sortByStringIndex(Object.keys(formatObj), format); |
|
710
|
|
|
var filterdKeys = filterFormatKeys(keys, format); |
|
711
|
|
|
var vstart = 0; // value start |
|
712
|
|
|
if (setHooks) { |
|
713
|
|
|
setHooks(hooks); |
|
714
|
|
|
} |
|
715
|
|
|
|
|
716
|
|
|
for (var i = 0; i < keys.length; i++) { |
|
717
|
|
|
var key = keys[i]; |
|
718
|
|
|
var fstart = format.indexOf(key); |
|
719
|
|
|
var _vstart = vstart; // next value start |
|
720
|
|
|
var val = null; |
|
721
|
|
|
var canSkip = false; |
|
722
|
|
|
var funcs = hooks.canSkip.get(key); |
|
723
|
|
|
|
|
724
|
|
|
vstart = vstart || fstart; |
|
725
|
|
|
|
|
726
|
|
|
for (var j = 0; j < funcs.length; j++) { |
|
727
|
|
|
if (funcs[j](formatObj)){ |
|
728
|
|
|
canSkip = true; |
|
729
|
|
|
break; |
|
730
|
|
|
} |
|
731
|
|
|
} |
|
732
|
|
|
if (fstart > -1 && !canSkip) { |
|
733
|
|
|
var sep = null; |
|
|
|
|
|
|
734
|
|
|
var stop = vstart + key.length; |
|
735
|
|
|
var fnext = -1; |
|
736
|
|
|
var nextKeyIdx = i + 1; |
|
737
|
|
|
_vstart += key.length; // set next value start if current key is found |
|
738
|
|
|
|
|
739
|
|
|
// get next format token used to determine separator |
|
740
|
|
|
while (fnext == -1 && nextKeyIdx < keys.length){ |
|
741
|
|
|
var nextKey = keys[nextKeyIdx]; |
|
742
|
|
|
nextKeyIdx += 1; |
|
743
|
|
|
if (filterdKeys.indexOf(nextKey) === -1) { |
|
744
|
|
|
continue; |
|
745
|
|
|
} |
|
746
|
|
|
fnext = nextKey ? format.indexOf(nextKey) : -1; // next format start |
|
747
|
|
|
} |
|
748
|
|
|
if (fnext > -1){ |
|
749
|
|
|
sep = format.slice(stop, fnext); |
|
750
|
|
|
if (sep) { |
|
751
|
|
|
var _stop = value.slice(vstart).indexOf(sep); |
|
752
|
|
|
if (_stop && _stop > -1){ |
|
753
|
|
|
stop = _stop + vstart; |
|
754
|
|
|
_vstart = stop + sep.length; |
|
755
|
|
|
} |
|
756
|
|
|
} |
|
757
|
|
|
} |
|
758
|
|
|
val = parseInt(value.slice(vstart, stop)); |
|
759
|
|
|
|
|
760
|
|
|
var funcs = hooks.updateValue.get(key); |
|
|
|
|
|
|
761
|
|
|
for (var k = 0; k < funcs.length; k++) { |
|
762
|
|
|
val = funcs[k](val, formatObj, vstart, stop); |
|
763
|
|
|
} |
|
764
|
|
|
} |
|
765
|
|
|
formatObj[key] = { index: vstart, value: val }; |
|
766
|
|
|
vstart = _vstart; // set next value start |
|
767
|
|
|
} |
|
768
|
|
|
return formatObj; |
|
769
|
|
|
} |
|
770
|
|
|
|
|
771
|
|
|
/** |
|
772
|
|
|
* @param {String} value |
|
773
|
|
|
* @param {DTS} settings |
|
774
|
|
|
* @returns {Date} date object |
|
775
|
|
|
*/ |
|
776
|
|
|
function parseDate(value, settings) { |
|
777
|
|
|
/** @type {{yyyy:number=, yy:number=, mm:number=, dd:number=}} */ |
|
778
|
|
|
var formatObj = {yyyy:null, yy:null, mm:null, dd:null}; |
|
779
|
|
|
var format = ((settings.dateFormat) || '').toLowerCase(); |
|
780
|
|
|
if (!format) { |
|
781
|
|
|
throw new TypeError('dateFormat not found (' + settings.dateFormat + ')'); |
|
782
|
|
|
} |
|
783
|
|
|
var formatObj = parseData(value, format, formatObj, function(hooks){ |
|
|
|
|
|
|
784
|
|
|
hooks.canSkip.add("yy", function(data){ |
|
785
|
|
|
return data["yyyy"].value; |
|
786
|
|
|
}); |
|
787
|
|
|
hooks.updateValue.add("yy", function(val){ |
|
788
|
|
|
return 100 * Math.floor(new Date().getFullYear() / 100) + val; |
|
789
|
|
|
}); |
|
790
|
|
|
}); |
|
791
|
|
|
var year = formatObj["yyyy"].value || formatObj["yy"].value; |
|
792
|
|
|
var month = formatObj["mm"].value - 1; |
|
793
|
|
|
var date = formatObj["dd"].value; |
|
794
|
|
|
var result = new Date(year, month, date); |
|
795
|
|
|
return result; |
|
796
|
|
|
} |
|
797
|
|
|
|
|
798
|
|
|
/** |
|
799
|
|
|
* @param {String} value |
|
800
|
|
|
* @param {DTS} settings |
|
801
|
|
|
* @returns {Number} time in milliseconds <= (24 * 60 * 60 * 1000) - 1 |
|
802
|
|
|
*/ |
|
803
|
|
|
function parseTime(value, settings) { |
|
804
|
|
|
var format = ((settings.timeFormat) || '').toLowerCase(); |
|
805
|
|
|
if (!format) { |
|
806
|
|
|
throw new TypeError('timeFormat not found (' + settings.timeFormat + ')'); |
|
807
|
|
|
} |
|
808
|
|
|
|
|
809
|
|
|
/** @type {{hh:number=, mm:number=, ss:number=, a:string=}} */ |
|
810
|
|
|
var formatObj = {hh:null, mm:null, ss:null, a:null}; |
|
811
|
|
|
var formatObj = parseData(value, format, formatObj, function(hooks){ |
|
|
|
|
|
|
812
|
|
|
hooks.updateValue.add("a", function(val, data, start, stop){ |
|
|
|
|
|
|
813
|
|
|
return value.slice(start, start + 2); |
|
814
|
|
|
}); |
|
815
|
|
|
}); |
|
816
|
|
|
var hours = formatObj["hh"].value; |
|
817
|
|
|
var minutes = formatObj["mm"].value; |
|
818
|
|
|
var seconds = formatObj["ss"].value; |
|
819
|
|
|
var am_pm = formatObj["a"].value; |
|
820
|
|
|
var am_pm_lower = am_pm ? am_pm.toLowerCase() : am_pm; |
|
821
|
|
|
if (am_pm && ["am", "pm"].indexOf(am_pm_lower) > -1){ |
|
822
|
|
|
if (am_pm_lower == 'am' && hours == 12){ |
|
823
|
|
|
hours = 0; |
|
824
|
|
|
} else if (am_pm_lower == 'pm') { |
|
825
|
|
|
hours += 12; |
|
826
|
|
|
} |
|
827
|
|
|
} |
|
828
|
|
|
var time = hours * 60 * 60 * 1000 + minutes * 60 * 1000 + seconds * 1000; |
|
829
|
|
|
return time; |
|
830
|
|
|
} |
|
831
|
|
|
|
|
832
|
|
|
/** |
|
833
|
|
|
* @param {Date} value |
|
834
|
|
|
* @param {DTS} settings |
|
835
|
|
|
* @returns {String} date string |
|
836
|
|
|
*/ |
|
837
|
|
|
function renderDate(value, settings) { |
|
838
|
|
|
var format = settings.dateFormat.toLowerCase(); |
|
839
|
|
|
var date = value.getDate(); |
|
840
|
|
|
var month = value.getMonth() + 1; |
|
841
|
|
|
var year = value.getFullYear(); |
|
842
|
|
|
var yearShort = year % 100; |
|
843
|
|
|
var formatObj = { |
|
844
|
|
|
dd: date < 10 ? "0" + date : date, |
|
845
|
|
|
mm: month < 10 ? "0" + month : month, |
|
846
|
|
|
yyyy: year, |
|
847
|
|
|
yy: yearShort < 10 ? "0" + yearShort : yearShort |
|
848
|
|
|
}; |
|
849
|
|
|
var str = format.replace(settings.dateFormatRegEx, function (found) { |
|
850
|
|
|
return formatObj[found]; |
|
851
|
|
|
}); |
|
852
|
|
|
return str; |
|
853
|
|
|
} |
|
854
|
|
|
|
|
855
|
|
|
/** |
|
856
|
|
|
* @param {Date} value |
|
857
|
|
|
* @param {DTS} settings |
|
858
|
|
|
* @returns {String} date string |
|
859
|
|
|
*/ |
|
860
|
|
|
function renderTime(value, settings) { |
|
861
|
|
|
var Format = settings.timeFormat; |
|
862
|
|
|
var format = Format.toLowerCase(); |
|
863
|
|
|
var hours = value.getHours(); |
|
864
|
|
|
var minutes = value.getMinutes(); |
|
865
|
|
|
var seconds = value.getSeconds(); |
|
866
|
|
|
var am_pm = null; |
|
867
|
|
|
var hh_am_pm = null; |
|
868
|
|
|
if (format.indexOf('a') > -1) { |
|
869
|
|
|
am_pm = hours >= 12 ? 'pm' : 'am'; |
|
870
|
|
|
am_pm = Format.indexOf('A') > -1 ? am_pm.toUpperCase() : am_pm; |
|
871
|
|
|
hh_am_pm = hours == 0 ? '12' : (hours > 12 ? hours%12 : hours); |
|
|
|
|
|
|
872
|
|
|
} |
|
873
|
|
|
var formatObj = { |
|
874
|
|
|
hh: am_pm ? hh_am_pm : (hours < 10 ? "0" + hours : hours), |
|
875
|
|
|
mm: minutes < 10 ? "0" + minutes : minutes, |
|
876
|
|
|
ss: seconds < 10 ? "0" + seconds : seconds, |
|
877
|
|
|
a: am_pm, |
|
878
|
|
|
}; |
|
879
|
|
|
var str = format.replace(settings.timeFormatRegEx, function (found) { |
|
880
|
|
|
return formatObj[found]; |
|
881
|
|
|
}); |
|
882
|
|
|
return str; |
|
883
|
|
|
} |
|
884
|
|
|
|
|
885
|
|
|
/** |
|
886
|
|
|
* checks if two dates are equal |
|
887
|
|
|
* @param {Date} date1 |
|
888
|
|
|
* @param {Date} date2 |
|
889
|
|
|
* @returns {Boolean} true or false |
|
890
|
|
|
*/ |
|
891
|
|
|
function isEqualDate(date1, date2) { |
|
892
|
|
|
if (!(date1 && date2)) return false; |
|
|
|
|
|
|
893
|
|
|
return (date1.getFullYear() == date2.getFullYear() && |
|
894
|
|
|
date1.getMonth() == date2.getMonth() && |
|
895
|
|
|
date1.getDate() == date2.getDate()); |
|
896
|
|
|
} |
|
897
|
|
|
|
|
898
|
|
|
/** |
|
899
|
|
|
* @param {Number} val |
|
900
|
|
|
* @param {Number} pad |
|
901
|
|
|
* @param {*} default_val |
|
902
|
|
|
* @returns {String} padded string |
|
903
|
|
|
*/ |
|
904
|
|
|
function padded(val, pad, default_val) { |
|
905
|
|
|
var default_val = default_val || 0; |
|
906
|
|
|
var valStr = '' + (parseInt(val) || default_val); |
|
907
|
|
|
var diff = Math.max(pad, valStr.length) - valStr.length; |
|
908
|
|
|
return ('' + default_val).repeat(diff) + valStr; |
|
909
|
|
|
} |
|
910
|
|
|
|
|
911
|
|
|
/** |
|
912
|
|
|
* @template X |
|
913
|
|
|
* @template Y |
|
914
|
|
|
* @param {X} obj |
|
915
|
|
|
* @param {Y} objDefaults |
|
916
|
|
|
* @returns {X|Y} merged object |
|
917
|
|
|
*/ |
|
918
|
|
|
function setDefaults(obj, objDefaults) { |
|
919
|
|
|
var keys = Object.keys(objDefaults); |
|
920
|
|
|
for (var i=0; i<keys.length; i++) { |
|
921
|
|
|
var key = keys[i]; |
|
922
|
|
|
if (!Object.prototype.hasOwnProperty.call(obj, key)) { |
|
923
|
|
|
obj[key] = objDefaults[key]; |
|
924
|
|
|
} |
|
925
|
|
|
} |
|
926
|
|
|
return obj; |
|
927
|
|
|
} |
|
928
|
|
|
|
|
929
|
|
|
|
|
930
|
|
|
window.dtsel = Object.create({},{ |
|
931
|
|
|
DTS: { value: DTS }, |
|
932
|
|
|
DTObj: { value: DTBox }, |
|
933
|
|
|
fn: { |
|
934
|
|
|
value: Object.defineProperties({}, { |
|
935
|
|
|
empty: { value: empty }, |
|
936
|
|
|
appendAfter: { |
|
937
|
|
|
value: function (newElem, refNode) { |
|
938
|
|
|
refNode.parentNode.insertBefore(newElem, refNode.nextSibling); |
|
939
|
|
|
}, |
|
940
|
|
|
}, |
|
941
|
|
|
getOffset: { value: getOffset }, |
|
942
|
|
|
parseDate: { value: parseDate }, |
|
943
|
|
|
renderDate: { value: renderDate }, |
|
944
|
|
|
parseTime: {value: parseTime}, |
|
945
|
|
|
renderTime: {value: renderTime}, |
|
946
|
|
|
setDefaults: {value: setDefaults}, |
|
947
|
|
|
}), |
|
948
|
|
|
}, |
|
949
|
|
|
}); |
|
950
|
|
|
})(); |
|
951
|
|
|
|